package com.eugene.enums;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.eugene.dao.MarketVariableDAO;
import com.eugene.element.FnCalendar;
import com.eugene.element.IrCurve;
import com.eugene.element.MarketVariable;
import com.eugene.element.Property;
import com.eugene.entity.MvData;
import com.eugene.entity.Scenario;

public enum EScenarioType {

	HS {
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
			List<MvData> mvData = sce.getMv().getMvHisData();
			List<MvData> mvSce = new ArrayList<MvData>();
			MvData rate;
			Scenario rstSce;
			
			double ratio;
			int timeHorizon = sce.getTimeHorizon();

			for(MvData aa: mvData){
				mvSce = MarketVariableDAO.getHistoryData(sce.getMvId(), aa.getMaturity()
											, baseDate ,sce.getSceNum()+timeHorizon);
				for(int i=0; i<mvSce.size() - timeHorizon; i++){
					rate = mvSce.get(i);
//					logger.debug("MvData : {},{}" , rate.getBaseDate(),rate.getMaturity());
					
					ratio = rate.getMvValue()/ mvSce.get(i+timeHorizon).getMvValue();
//					logger.debug("MvValue : {},{}" , i,ratio);
					
					rstSce = new Scenario(sce.getSceDefId()+"_"+rate.getBaseDate()
									,sce.getMvId(), aa.getMaturity(),sce.getSceSetId());
					rstSce.setPower(1.0);
					rstSce.setSpread(0.0);
					rstSce.setCoefficient(ratio);
					rst.add(rstSce);
				}
			}
			return rst;
		}
	},
	MC,
	VaR{
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
			List<MvData> mvData = sce.getMv().getMvHisData();

			double tweak =1 + sce.getTweakValue();
			Scenario rstSce;
			
			for(MvData aa:mvData){
				for(MvData bb: mvData){
					rstSce = new Scenario(sce.getSceDefId()+"_"+sce.getMvId()+"_"+aa.getMaturity().toString()
						, sce.getMvId(), bb.getMaturity(), sce.getSceSetId());
				
					if(aa.getMaturity().equals(bb.getMaturity())){
						rstSce.setCoefficient(tweak);
					}else{
						rstSce.setCoefficient(1.0);
					}
					rstSce.setPower(1.0);
					rstSce.setSpread(0.0);
					rst.add(rstSce);
				}
			}
			return rst;
		}
	},
	CREDIT {
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
//			Scenario sceRst;
			if(!sce.getMv().getMvTypeE().equals(EMarketVariableType.IR)){
//			if(!sce.getMv().getMvTypeId().equals("IR")){	
				Scenario rstSce;
				rstSce = sce;
				rstSce.setSceId(sce.getSceDefId());
				rstSce.setCoefficient(1.0);
				rstSce.setPower(1.0);
				rstSce.setSpread(0.0);
				rst.add(rstSce);
				return rst;
			}
			
			for (MarketVariable mv : MarketVariableDAO.getCreditGradeMarketVariable(baseDate)) {
				for (MvData mvData : mv.getMvHisData()) {
					Scenario rstSce ;
					rstSce = new Scenario(sce.getSceDefId()+ "_" + ((IrCurve) mv).getCreditGrade(),
											sce.getMvId(), mvData.getMaturity(), sce.getSceSetId());
					rstSce.setPower(1.0);
					rstSce.setCoefficient(0.0);
					rstSce.setSpread(mvData.getMvValue());
					rst.add(rstSce);
				}
			}
			return rst;
		}
	},
	BACKTEST{
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
			List<MvData> mvData = sce.getMv().getMvHisData();
			
			Scenario rstSce;
			for(MvData aa: mvData){
				rstSce = new Scenario(sce.getSceDefId()+ "_" + baseDate ,
									sce.getMvId(), aa.getMaturity(), sce.getSceSetId());
				rstSce.setCoefficient(0.0);
				rstSce.setPower(0.0);
				rstSce.setSpread(aa.getMvValue());
				rst.add(rstSce);
			}
			return rst;
		}
	},
	FLAT {
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
			List<MvData> mvData = sce.getMv().getMvHisData();
			
			Scenario rstSce;
			double spread = sce.getTweakValue();
			for(MvData aa:mvData){
				rstSce = new Scenario(sce.getSceDefId(), sce.getMvId(), aa.getMaturity(), sce.getSceSetId());
				rstSce.setCoefficient(0.0);
				rstSce.setPower(1.0);
				rstSce.setSpread(spread);
				rst.add(rstSce);
			}	
			return rst;
		}
	},
	STEEP {
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
			List<MvData> mvData = sce.getMv().getMvHisData();
			double spread = 0.0;
			double tweak = sce.getTweakValue();
			String matId = Property.getProperity("maturityForSteep").getStringValue();
			Scenario rstSce;
			
			for (MvData aa : mvData) {
				if (aa.getMaturity().toString().equals(matId)) {
					spread = -(tweak - 1) * aa.getMvValue();
					break;
				}
			}

			for (MvData aa : mvData) {
				rstSce = new Scenario(sce.getSceDefId(), sce.getMvId(), aa.getMaturity(), sce.getSceSetId());
				rstSce.setCoefficient(tweak);
				rstSce.setPower(1.0);
				rstSce.setSpread(spread);
				if (tweak * aa.getMvValue() + spread <= 0) {
					logger.warn("Negative Scenario market Varaiable generated " +
								"by sceDefId {} is change to 0", sce.getSceDefId());
					rstSce.setCoefficient(0.0);
					rstSce.setSpread(0.0);
				}
				rst.add(rstSce);
			}
			return rst;
		}
	},
	
	SHIFT {
		public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
			List<Scenario> rst = new ArrayList<Scenario>();
			List<MvData> mvData = sce.getMv().getMvHisData();
			
			Scenario rstSce;
			double spread = sce.getTweakValue();
			for(MvData aa:mvData){
				rstSce = new Scenario(sce.getSceDefId(), sce.getMvId(), aa.getMaturity(), sce.getSceSetId());
				rstSce.setCoefficient(1.0);
				rstSce.setPower(1.0);
				rstSce.setSpread(spread);
				rst.add(rstSce);
			}	
			return rst;
		}
	},
	ADD,
	MULTI,
	KEY_IN ;

	
	
	private final static Logger logger = LoggerFactory
			.getLogger(EScenarioType.class);

//	public Scenario getScenarioRst(Scenario sce, FnCalendar baseDate) {
//		return sce;
//	}

	public List<Scenario> createScenario(Scenario sce, FnCalendar baseDate) {
		List<Scenario> scenarios = new ArrayList<Scenario>();
		return scenarios;
	}
	
}
